/**
 * Created By xiyuan
 * Author server@xiyuan.name (惜缘叛逆)
 * DateTime 2019/8/5 11:23 AM
 * Describe javascript功能描述
 * MIT License http://www.opensource.org/licenses/mit-license.php
 */
const net = require('net');
// 请求工具包
const request = require('request');

// 端口生成
async function genPort(ignores) {
	ignores = Array.isArray(ignores) ? ignores : [8000, 8080, 9000, 3000];
	// 起始端口
	let start = 5001;
	// 结束端口
	let end = 65535;
	let port = start - 1;
	let arr = function (list) {
		for (; port <= end; port++) {
			list.push(port)
		}
		return list;
	}([]);
	
	// 随机取得索引
	let index = Number(Math.random().toString().replace('0.', '')) % arr.length;
	
	// 随机挑选需要使用的端口
	let usePort = arr[index];
	
	// 检查索引是否在忽略列表中
	if (ignores.some(function (port) {
		return port == usePort
	})) {
		usePort = await genPort(start, end, ignores);
	}
	
	// 检查端口是否被占用
	let isUse = await portAvailability(usePort);
	
	return isUse ? usePort : await genPort(ignores);
}

// 检查端口是否可用
function portAvailability(port) {
	const server = net.createServer().listen(port)
	return new Promise((resolve, reject) => {
		server.on('listening', () => {
			server.close()
			resolve(true)
		})
		
		server.on('error', (err) => {
			// 端口被占用
			if (err.code === 'EADDRINUSE') {
				reject(false)
			} else {
				reject(false)
			}
		})
	})
}

// 请求处理
function requestHandle(requestURL, user, pwd, options = {}) {
	options.method = (options.method || 'get').toLocaleUpperCase();
	options = {
		...options,
		url: requestURL,
		headers: {
			"Accept": "*/*",
			"Accept-Encoding": "gzip, deflate, br",
			"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6",
			"Authorization": "Basic " + Buffer.from(user + ':' + pwd).toString('base64'),
			"Connection": "keep-alive",
			"Host": "localhost:3000",
			"Referer": "http://localhost:3000/static/",
			"Sec-Fetch-Mode": "cors",
			"Sec-Fetch-Site": "same-origin",
			"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36",
		},
	};
	
	return new Promise(function (resolve, reject) {
		request(options, function (error, response, body) {
			let info = null;
			try {
				info = JSON.parse(body)
			}
			catch (e) {
			}
			
			// 检查接口是否出错
			if (!error && response.statusCode == 200) {
				resolve({info, body, response})
			} else {
				reject({error, body, response})
			}
		});
	})
}

// 客户端接口请求
function clientApi({user = 'admin', pwd = 'admin', interface = 'status', host = '0.0.0.0', port = 7400, options = {}}) {
	// 接口字典
	const apiMap = {
		config: '/config',
		upload: '/config',
		reload: '/reload',
		status: '/status'
	}
	// 请求地址
	const requestURL = 'http://' + host + ':' + port + '/api' + apiMap[interface];
	// 请求处理
	return requestHandle(requestURL, user, pwd, options = {})
}

// 接口请求
function serverApi({user = 'admin', pwd = 'admin', interface = 'serverinfo', host = '0.0.0.0', port = 3000, options = {}}) {
	// 接口字典
	const apiMap = {
		tcp: '/proxy/tcp',
		udp: '/proxy/udp',
		stcp: '/proxy/stcp',
		serverinfo: '/serverinfo'
	}
	// 请求地址
	const requestURL = 'http://' + host + ':' + port + '/api' + apiMap[interface];
	// 请求处理
	return requestHandle(requestURL, user, pwd, options)
}

module.exports = {
	// 端口生成
	genPort,
	// 端口是否可用
	portAvailability,
	// 接口请求
	serverApi,
	clientApi,
}